Shader "Dou/UIParticle"
{
    Properties
    {
        [Enum(UnityEngine.Rendering.BlendMode)] _Src ("Src", Float) = 5
		[Enum(UnityEngine.Rendering.BlendMode)] _Dst ("Dst", Float) = 10
		[Enum(UnityEngine.Rendering.CompareFunction)] _ZTestMode ("Z TestMode", Float) = 4
		[Enum(Off, 0, On, 1)] _ZWriteMode ("Z WriteMode", Float) = 0
		[Enum(UnityEngine.Rendering.CullMode)] _CullMode ("Cull Mode", Float) = 2
		[Enum(RGB, 14, RGBA, 15)] _ColorMask ("ColorMask", Float) = 15
        
        [ForceInt] _Stencil ("Stencil ID", Float) = 0
		[Enum(UnityEngine.Rendering.CompareFunction)] _StencilComp ("Stencil Comparison", Float) = 8
        [Enum(UnityEngine.Rendering.StencilOp)] _StencilOp ("Stencil Operation", Float) = 0
		[IntRange] _StencilWriteMask ("Stencil Write Mask", Range(0, 255)) = 255
        [IntRange] _StencilReadMask ("Stencil Read Mask", Range(0, 255)) = 255
        
        [Toggle] _UseCustomData ("Use CustomData 勾选后使用Custom控制", float) = 0

		[Toggle(USE_SPLITCHANNEL)] Use_SplitChannel ("Split RGB 通道抖动", Float) = 0
		_SplitValue("SplitValue", float) = 0

		[Toggle] Use_ScreenPos ("Use ScreenPosUV 屏幕UV ", Float) = 0
		[HDR] _MainTexColor ("MainTex Color", Color) = (0, 0, 0, 1)
		[HDR] _MainTexBackColor ("MainTex BackColor", Color) = (1, 1, 1, 1)
		[MainTexture] _MainTexture ("MainTexture 主贴图/正面颜色/背面颜色", 2D) = "white" {}
		_MainTex_UVTiling_UVSpeed("MainTex_UVTiling_UVSpeed", Vector) = (1, 1, 0, 0)
		_MainTex_UVOffset_CenterScale("MainTex_UVOffset/Z ：UV中心缩放", Vector) = (0, 0, 0, 0)
		
		[Toggle(USE_BLEND_TEXTURE)] USE_BLEND_TEXTURE ("Blend Texture 混合贴图", Float) = 0
		_BlendMask ("Blend Mask 混合遮罩", 2D) = "black" {}
		_BlendMask_UVTiling_UVSpeed ("BlendMask_UVTiling_UVSpeed", Vector) = (1, 1, 0, 0)
		_BlendMask_UVOffset ("BlendMask_UVOffset (XY)", Vector) = (0, 0, 0, 0)
		[HDR] _BlendTexColor ("BlendTex Color", Color) = (1, 1, 1, 1)
		_BlendTexture ("Blend Texture 混合贴图", 2D) = "white"{}
		_BlendTexture_UVTiling_UVSpeed ("BlendTex_UVTiling_UVSpeed", Vector) = (1, 1, 0, 0)
		_BlendTexture_UVOffset ("BlendTexture_UVOffset (XY)", Vector) = (0, 0, 0, 0)
		
		[Toggle(USE_COLOR_ADJUSTMENT)] USE_COLOR_ADJUSTMENT ("ColorAdjustment 颜色调整", Float) = 0
		_HueAdjust ("Hue 色调", Range(-1, 1)) = 0
		_SaturationAdjust ("Saturation 饱和度", Range(-1, 1)) = 0
		_ValueAdjust ("Value 明度", Range(-1, 1)) = 0

		[KeywordEnum(Off, Hard, Soft)] _DissolveMode ("Dissolve Mode 溶解", Float) = 0
		_DissolveTexture ("Dissolve Texture", 2D) = "white" {}
		_DissolveTex_UVTiling_UVSpeed ("DissolveTex_UVTiling_UVSpeed", Vector) = (1, 1, 0, 0)
		_DissolveTex_UVOffset ("DissolveTex_UVOffset (XY)", Vector) = (0, 0, 0, 0)
		_DissolveValue ("Dissolve Value 溶解值", float) = 0
		_EdgeHardness ("Edge Hardness 溶解边缘硬度", Range(0, 1)) = 0
		[HDR] __EdgeColor ("Edge Color 边缘颜色", Color) = (0, 0, 0, 0)
		_EdgeWidth ("Edge Width 边缘宽度", Float) = 0
    	
		[Toggle(USE_DISTORTION)] USE_DISTORTION ("Distortion 扰动", Float) = 0
		_DistortionTexture ("Distortion Texture", 2D) = "white" {}
		_DistortionTex_UVTiling_UVSpeed ("DistortionTex_UVTiling_UVSpeed", Vector) = (1, 1, 0, 0)
		_DistortionTex_UVOffset ("DistortionTex_UVOffset (XY)", Vector) = (0, 0, 0, 0)
		_MainTexDistortionValue ("MainTex Distortion Value 主贴图扰动", Float) = 0
		_DissolveDistortionValue ("Dissolve Distortion Value 溶解图扰动", Float) = 0
    	
		[Toggle(USE_MASK)] USE_MASK ("Mask 遮罩图", Float) = 0
		_MaskTexture ("Mask Texture", 2D) = "white" {}
		_MaskTex_UVTiling_UVSpeed ("MaskTex_UVTiling_UVSpeed", Vector) = (1, 1, 0, 0)
		_MaskTex_UVOffset ("MaskTex_UVOffset (XY)", Vector) = (0, 0, 0, 0)
    	
		[Toggle] _FresnelToggle ("Fresnel 菲尼尔", Float) = 0
		[HDR] _FresnelColor ("Fresnel Color", Color) = (1, 1, 1, 1)
		_FresnelStrength ("Fresnel Strength", Float) = 1
		_FresnelPower ("Fresnel Power", Float) = 1
		[Toggle] _FresnelAsTrans ("Fresnel As Transparence 边缘剔除效果", Float) = 0
		[Toggle] _vColorControl ("Fresnel vColor Control  粒子系统是否影响Alpha", Float) = 0
    	
		[Toggle] _BlackWhiteToggle ("BlackWhite  黑白闪", int) = 0
		_BlackWhiteStep ("BlackWhite Step 插值", Float) = 0.5
		_BlackToWhiteValue ("Black To White Value 黑白过度", float) = 0
    	
		[Toggle] _GroundFadeToggle ("GroundFade 软粒子", int) = 0
		_FadeValue ("Fade Value 高度差值", float) = 0
		_FadeRamp ("Fade Ramp 软边范围", float) = 5
		[Toggle(USE_FADELOCALPOS)] _FadeLocalPos ("Use LocalPos 开启本地坐标", Float) = 0
		
		[HideInInspector] _MainTex ("Texture", 2D) = "white" {}
		[HideInInspector] _MaskRect ("MaskRect", vector) = (0, 0, 0, 0)
		[HideInInspector] _WorldPsPos ("WorldPsPos",vector) = (0, 0, 0, 0)
    }
    SubShader
    {
    	Tags { "RenderType"="Transparent" "Queue"="Transparent" "RenderPipeline"="UniversalPipeline" }

		Blend [_Src] [_Dst]
		AlphaToMask Off
		Cull [_CullMode]
		ColorMask [_ColorMask]
		ZWrite [_ZWriteMode]
		ZTest [_ZTestMode]
		Stencil
        {
            Ref [_Stencil]
            Comp [_StencilComp]
            Pass [_StencilOp]
            ReadMask [_StencilReadMask]
            WriteMask [_StencilWriteMask]
        }
		
		Pass
		{
			Name "Unlit"
			Tags { "LightMode"="UniversalForward" }
			
			HLSLPROGRAM

			#pragma vertex vert
			#pragma fragment frag
			#pragma target 3.0
			#include "Packages/com.unity.render-pipelines.universal/ShaderLibrary/Core.hlsl"
			#include "Packages/com.unity.render-pipelines.core/ShaderLibrary/Color.hlsl"
			#pragma shader_feature_local _DISSOLVEMODE_OFF _DISSOLVEMODE_HARD _DISSOLVEMODE_SOFT
			#pragma multi_compile _ USE_MASK
			#pragma multi_compile _ USE_UI_MASK_RECT
			#pragma shader_feature_local USE_DISTORTION
			#pragma shader_feature_local USE_SPLITCHANNEL
			#pragma shader_feature_local USE_COLOR_ADJUSTMENT
			#pragma shader_feature_local USE_FADELOCALPOS
			#pragma shader_feature_local USE_BLEND_TEXTURE
			
			// GPU Instancing
            #pragma multi_compile_instancing
            #pragma multi_compile _ DOTS_INSTANCING_ON

			float _ZTestMode;
			float _ZWriteMode;
			float _Dst;
			float _CullMode;
			float _Src;

			float _BlackWhiteToggle;
			float _FresnelToggle;
			float4 __EdgeColor;

			float4 _MainTexColor;
			sampler2D _MainTexture;
			float4 _MainTex_UVTiling_UVSpeed;
			float4 _MainTex_UVOffset_CenterScale;
			float Use_ScreenPos;
			float _UseCustomData;

			float4 _BlendTexColor;
			sampler2D _BlendTexture;
			float4 _BlendMask_UVTiling_UVSpeed;
			float4 _BlendMask_UVOffset;
			sampler2D _BlendMask;
			float4 _BlendTexture_UVTiling_UVSpeed;
			float4 _BlendTexture_UVOffset;
			
			sampler2D _DistortionTexture;
			float4 _DistortionTex_UVTiling_UVSpeed;
			float4 _DistortionTex_UVOffset;
			float _MainTexDistortionValue;
			float _DissolveDistortionValue;

			float _SplitValue;

			float _DissolveValue;
			float _EdgeHardness;
			sampler2D _DissolveTexture;
			float4 _DissolveTex_UVTiling_UVSpeed;
			float4 _DissolveTex_UVOffset;
			float _EdgeWidth;

			float4 _FresnelColor;
			float _FresnelPower;
			float _FresnelStrength;
			float _FresnelAsTrans;
			float _vColorControl;
			
			float _BlackWhiteStep;
			float _BlackToWhiteValue;
			float4 _MainTexBackColor;

			float _GroundFadeToggle;
			float _FadeValue;
			float _FadeRamp;

			sampler2D _MaskTexture;
			float4 _MaskTex_UVTiling_UVSpeed;
			float4 _MaskTex_UVOffset;

			float _HueAdjust;
			float _SaturationAdjust;
			float _ValueAdjust;

			float4 _MaskRect;
			float4 _WorldPsPos;

			struct appdata
			{
				float4 vertex : POSITION;
				float4 color : COLOR;
				float4 texcoord : TEXCOORD0;
				float4 texcoord1 : TEXCOORD1;
				float4 texcoord2 : TEXCOORD2;
				float3 normal : NORMAL;
				UNITY_VERTEX_INPUT_INSTANCE_ID
			};
			
			struct v2f
			{
				float4 pos : SV_POSITION;
				float3 worldPos : TEXCOORD0;
				float4 uv1 : TEXCOORD1;

				float4 customData1 : TEXCOORD3;
				float4 customData2 : TEXCOORD4;

				float3 worldNormal : TEXCOORD5;

				float4 color : COLOR;
				float4 scrPos:TEXCOORD6;
				#ifdef USE_FADELOCALPOS
					float3 worldModelPos : TEXCOORD7;
				#endif
				
				UNITY_VERTEX_INPUT_INSTANCE_ID
				UNITY_VERTEX_OUTPUT_STEREO
			};

			v2f vert(appdata v)
			{
				v2f o;

				UNITY_SETUP_INSTANCE_ID(v);
                UNITY_TRANSFER_INSTANCE_ID(v, o);
                UNITY_INITIALIZE_VERTEX_OUTPUT_STEREO(o);

				o.worldNormal = TransformObjectToWorldNormal(v.normal);
				
				o.uv1.xy = v.texcoord.xy;
				o.uv1.zw = v.texcoord.xy;

				o.customData1 = v.texcoord1;
				o.customData2 = v.texcoord2;
				o.color = v.color;
				o.worldPos = TransformObjectToWorld(v.vertex.xyz);
				
				o.pos = TransformObjectToHClip(v.vertex.xyz);
				o.scrPos = ComputeScreenPos(o.pos);
				#ifdef USE_FADELOCALPOS
					o.worldModelPos = mul(unity_ObjectToWorld, half4(0, 0, 0, 1)).xyz;
				#endif

				return o;
			}

			float3 rgb2hsv(float3 c)
			{
				float4 K = float4(0.0, -1.0 / 3.0, 2.0 / 3.0, -1.0);
				float4 p = lerp(float4(c.bg, K.wz), float4(c.gb, K.xy), step(c.b, c.g));
				float4 q = lerp(float4(p.xyw, c.r), float4(c.r, p.yzx), step(p.x, c.r));

				float d = q.x - min(q.w, q.y);
				float e = 1.0e-10;
				return float3(abs(q.z + (q.w - q.y) / (6.0 * d + e)), d / (q.x + e), q.x);
			}

			float3 hsv2rgb(float3 c)
			{
				c = float3(c.x, clamp(c.yz, 0.0, 1.0));
				float4 K = float4(1.0, 2.0 / 3.0, 1.0 / 3.0, 3.0);
				float3 p = abs(frac(c.xxx + K.xyz) * 6.0 - K.www);
				return c.z * lerp(K.xxx, clamp(p - K.xxx, 0.0, 1.0), c.y);
			}
			
			half4 frag(v2f i, float vface : VFACE) : SV_Target
			{
				UNITY_SETUP_INSTANCE_ID(i);
				UNITY_SETUP_STEREO_EYE_INDEX_POST_VERTEX(i);
				
				i.uv1.xy = lerp(i.uv1.xy, i.scrPos.xy / i.scrPos.w, Use_ScreenPos);
				
				half2 uvScale = i.uv1.xy - 0.5;
				float scaleValue = lerp(_MainTex_UVOffset_CenterScale.z, i.customData2.y, _UseCustomData);
                uvScale *= (scaleValue + 1);
				uvScale += 0.5;
				
				float2 uvOffset = lerp(_MainTex_UVOffset_CenterScale.xy, i.customData2.zw, _UseCustomData);

				float2 mainTexUV = uvScale * _MainTex_UVTiling_UVSpeed.xy + _Time.y * _MainTex_UVTiling_UVSpeed.zw + uvOffset;

				#ifdef USE_DISTORTION
					float2 distortionUV = i.uv1.xy * _DistortionTex_UVTiling_UVSpeed.xy + _Time.y * _DistortionTex_UVTiling_UVSpeed.zw + _DistortionTex_UVOffset.xy;
					float4 distortionTex = tex2D(_DistortionTexture, distortionUV);
					float mainTexDistortValue = lerp(_MainTexDistortionValue, i.customData1.z, _UseCustomData);
					mainTexUV = lerp(mainTexUV, distortionTex.rg, mainTexDistortValue * 0.1);
				#endif

				float4 mainTex = tex2D(_MainTexture, mainTexUV);

				#ifdef USE_BLEND_TEXTURE
					float2 blendTexUV = i.uv1.xy * _BlendTexture_UVTiling_UVSpeed.xy + _Time.y * _BlendTexture_UVTiling_UVSpeed.zw + _BlendTexture_UVOffset.xy;
					float4 blendTex = tex2D(_BlendTexture, blendTexUV) * _BlendTexColor;
					float2 blendMaskUV = i.uv1.xy * _BlendMask_UVTiling_UVSpeed.xy + _Time.y * _BlendMask_UVTiling_UVSpeed.zw + _BlendMask_UVOffset.xy;
					float blendMask = tex2D(_BlendMask, blendMaskUV).r;
					mainTex = lerp(mainTex, blendTex, blendMask);
				#endif

				#ifdef USE_SPLITCHANNEL
					float splitValue = lerp(_SplitValue, i.customData1.y, _UseCustomData) * 0.05;
					float4 mainTex_R = tex2D(_MainTexture, float2(mainTexUV.x + splitValue, mainTexUV.y));
					float4 mainTex_B = tex2D(_MainTexture, float2(mainTexUV.x, mainTexUV.y - splitValue));
					mainTex = float4(mainTex_R.r, mainTex.g, mainTex_B.b, mainTex_R.a * mainTex.a * mainTex_B.a);
				#endif

				#ifdef USE_COLOR_ADJUSTMENT
					float3 albedo_hsv = rgb2hsv(mainTex.rgb);
					mainTex.rgb = hsv2rgb(albedo_hsv + float3(_HueAdjust, _SaturationAdjust, _ValueAdjust));
				#endif

				float4 finalColor = mainTex * i.color;
				finalColor *= vface > 0 ? _MainTexColor : _MainTexBackColor;

				float dissolveMode = 1;

				#if defined(_DISSOLVEMODE_SOFT) || defined(_DISSOLVEMODE_HARD)
					float2 dissolveUV = i.uv1.xy * _DissolveTex_UVTiling_UVSpeed.xy + _Time.y * _DissolveTex_UVTiling_UVSpeed.zw + _DissolveTex_UVOffset.xy;

					#ifdef USE_DISTORTION
						float dissolveDistortionValue = lerp(_DissolveDistortionValue, i.customData1.w, _UseCustomData);
						dissolveUV = lerp(dissolveUV, distortionTex.rg, dissolveDistortionValue * 0.1);
					#endif
 
					float dissolveValue = lerp(_DissolveValue, i.customData1.x, _UseCustomData);
					float dissolveTex = clamp(tex2D(_DissolveTexture, dissolveUV).r + (dissolveValue * 2 - 1), 0.0, 1.0);
					float dissolveEdge = smoothstep(_EdgeHardness * 0.5, 0.5, dissolveTex - _EdgeWidth);
					finalColor = lerp(__EdgeColor, finalColor, dissolveEdge);
					
					dissolveMode = dissolveTex;
					#if defined(_DISSOLVEMODE_HARD)
						dissolveMode = step(0.5, dissolveTex);
					#endif
				#endif

				float grayScale = Luminance(finalColor.rgb);
				grayScale = step(grayScale, _BlackWhiteStep);
				float grayValue = lerp(_BlackToWhiteValue, i.customData2.x, _UseCustomData);
				float gray = lerp(grayScale, 1.0 - grayScale, grayValue);
				finalColor.rgb = _BlackWhiteToggle ? i.color.rgb * gray : finalColor.rgb;

				float3 worldView = normalize(GetCameraPositionWS() - i.worldPos);
				float ndv = saturate(dot(i.worldNormal, worldView));
				float fresnel = pow(max(0.001, 1 - ndv), _FresnelPower);
				float4 fresnelColor = fresnel * _FresnelColor;
				fresnelColor.rgb *= _FresnelStrength;
				finalColor.rgb += _FresnelToggle * fresnelColor.rgb;
				finalColor.a = saturate(i.color.a * mainTex.a * _MainTexColor.a + lerp(1, i.color.a, _vColorControl) * (fresnelColor.a * _FresnelToggle));
				finalColor.a *= lerp(1, saturate(1 - fresnel*_FresnelStrength), _FresnelAsTrans * _FresnelToggle);
				finalColor.a *= dissolveMode;

				#ifdef USE_FADELOCALPOS
					float particlePos = lerp(i.worldModelPos.y, _WorldPsPos.y, _WorldPsPos.w);
					float ramp = saturate(_FadeRamp * (i.worldPos.y - particlePos - _FadeValue));
				#else
					float ramp = saturate(_FadeRamp * (i.worldPos.y - _FadeValue));
				#endif
				finalColor.a *= lerp(1, ramp, _GroundFadeToggle);

				#ifdef USE_MASK
					float2 maskUV = i.uv1.xy * _MaskTex_UVTiling_UVSpeed.xy + _Time.y * _MaskTex_UVTiling_UVSpeed.zw + _MaskTex_UVOffset.xy;
					float maskTex = tex2D(_MaskTexture, maskUV).r;
					finalColor.a *= maskTex;
				#endif

				#ifdef USE_UI_MASK_RECT
					if (_MaskRect.x != 0 || _MaskRect.y != 0 || _MaskRect.z != 0 || _MaskRect.w != 0)
					{
						finalColor.a *= (i.worldPos.x >= _MaskRect.x);
						finalColor.a *= (i.worldPos.x <= _MaskRect.z);
						finalColor.a *= (i.worldPos.y >= _MaskRect.y);
						finalColor.a *= (i.worldPos.y <= _MaskRect.w);
					}
				#endif
				
				return finalColor;
			}
			ENDHLSL
		}
    }
	
	CustomEditor "Dou.UIParticleShaderEditor"
}
